{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from __future__ import division\n",
    "\n",
    "from vnpy.trader.vtObject import VtBarData\n",
    "from vnpy.trader.vtConstant import EMPTY_STRING\n",
    "from vnpy.trader.app.ctaStrategy.ctaTemplate import (CtaTemplate,\n",
    "                                                     BarGenerator,\n",
    "                                                     ArrayManager)\n",
    "import talib as ta\n",
    "\n",
    "\n",
    "########################################################################\n",
    "class RegressionStrategy(CtaTemplate):\n",
    "    className = 'RegressionStrategy'\n",
    "    author = 'ChannelCMT'\n",
    "\n",
    "    # 策略交易标的的列表\n",
    "    symbolList = []  # 初始化为空\n",
    "    posDict = {}  # 初始化仓位字典\n",
    "\n",
    "    # 多空仓位\n",
    "    Longpos = EMPTY_STRING  # 多头品种仓位\n",
    "    Shortpos = EMPTY_STRING  # 空头品种仓位\n",
    "\n",
    "    # 策略参数\n",
    "    amWindow = 100\n",
    "    trendFastWindow = 10  # 布林通道窗口数\n",
    "    trendSlowWindow = 40  # 布林通道的偏差\n",
    "    volatilityWindow = 10  # CCI窗口数\n",
    "    volatilityThresholdWindow = 10\n",
    "    SignalFastWindow = 30\n",
    "    revertPercent = 0.04\n",
    "    stopRatio = 0.04  # 止损比例\n",
    "    profitMultiplier = 0.7\n",
    "    initDays = 2  # 初始化数据所用的天数\n",
    "    fixedSize = 1  # 每次交易的数量\n",
    "\n",
    "    # 策略变量\n",
    "    #     intraTradeHigh = 0                  # 持仓期内的最高点\n",
    "    #     intraTradeLow = 0                   # 持仓期内的最低点\n",
    "    #     longStop = 0                        # 多头止损\n",
    "    #     shortStop = 0                       # 空头止损\n",
    "    Trend = 0\n",
    "    Volatility = 0\n",
    "    transactionPrice = 0\n",
    "\n",
    "    # 参数列表，保存了参数的名称\n",
    "    paramList = ['name',\n",
    "                 'className',\n",
    "                 'author',\n",
    "                 'symbolList',\n",
    "                 'amWindow',\n",
    "                 'trendFastWindow',\n",
    "                 'trendSlowWindow',\n",
    "                 'volatilityWindow',\n",
    "                 'volatilityThresholdWindow',\n",
    "                 'SignalFastWindow',\n",
    "                 'revertPercent',\n",
    "                 'stopRatio',\n",
    "                 'profitMultiplier',\n",
    "                 'initDays',\n",
    "                 'fixedSize']\n",
    "\n",
    "    # 变量列表，保存了变量的名称\n",
    "    varList = ['inited',\n",
    "               'trading',\n",
    "               'posDict',\n",
    "               'Volatility',\n",
    "               'Trend']\n",
    "\n",
    "    # 同步列表，保存了需要保存到数据库的变量名称\n",
    "    syncList = ['posDict',\n",
    "                'intraTradeHigh',\n",
    "                'intraTradeLow']\n",
    "\n",
    "    # ----------------------------------------------------------------------\n",
    "    def __init__(self, ctaEngine, setting):\n",
    "        \"\"\"Constructor\"\"\"\n",
    "        super(RegressionStrategy, self).__init__(ctaEngine, setting)\n",
    "\n",
    "        # 生成仓位记录的字典\n",
    "        symbol = self.symbolList[0]\n",
    "        self.Longpos = symbol.replace('.', '_') + \"_LONG\"\n",
    "        self.Shortpos = symbol.replace('.', '_') + \"_SHORT\"\n",
    "\n",
    "        self.bg60Dict = {\n",
    "            sym: BarGenerator(self.onBar, 60, self.on60minBar)\n",
    "            for sym in self.symbolList\n",
    "        }\n",
    "\n",
    "        self.bg30Dict = {\n",
    "            sym: BarGenerator(self.onBar, 30, self.on30minBar)\n",
    "            for sym in self.symbolList\n",
    "        }\n",
    "\n",
    "        self.bg15Dict = {\n",
    "            sym: BarGenerator(self.onBar, 15, self.on15minBar)\n",
    "            for sym in self.symbolList\n",
    "        }\n",
    "\n",
    "        self.am60Dict = {\n",
    "            sym: ArrayManager(size=self.amWindow)\n",
    "            for sym in self.symbolList\n",
    "        }\n",
    "\n",
    "        self.am30Dict = {\n",
    "            sym: ArrayManager(size=self.amWindow)\n",
    "            for sym in self.symbolList\n",
    "        }\n",
    "\n",
    "        self.am15Dict = {\n",
    "            sym: ArrayManager(size=self.amWindow)\n",
    "            for sym in self.symbolList\n",
    "        }\n",
    "\n",
    "    # ----------------------------------------------------------------------\n",
    "    def onInit(self):\n",
    "        \"\"\"初始化策略（必须由用户继承实现）\"\"\"\n",
    "        self.writeCtaLog(u'%s策略初始化' % self.name)\n",
    "        self.ctaEngine.initPosition(self)\n",
    "        # 载入历史数据，并采用回放计算的方式初始化策略数值\n",
    "        initData = self.loadBar(self.initDays)\n",
    "        for bar in initData:\n",
    "            self.onBar(bar)\n",
    "\n",
    "        self.putEvent()\n",
    "\n",
    "    # ----------------------------------------------------------------------\n",
    "    def onStart(self):\n",
    "        \"\"\"启动策略（必须由用户继承实现）\"\"\"\n",
    "        self.writeCtaLog(u'%s策略启动' % self.name)\n",
    "        self.putEvent()\n",
    "\n",
    "    # ----------------------------------------------------------------------\n",
    "    def onStop(self):\n",
    "        \"\"\"停止策略（必须由用户继承实现）\"\"\"\n",
    "        self.writeCtaLog(u'%s策略停止' % self.name)\n",
    "        self.putEvent()\n",
    "\n",
    "    # ----------------------------------------------------------------------\n",
    "    def onTick(self, tick):\n",
    "        \"\"\"收到行情TICK推送（必须由用户继承实现）\"\"\"\n",
    "        self.bgDict[tick.vtSymbol].updateTick(tick)\n",
    "\n",
    "    # ----------------------------------------------------------------------\n",
    "    def onBar(self, bar):\n",
    "        \"\"\"收到Bar推送（必须由用户继承实现）\"\"\"\n",
    "        symbol = bar.vtSymbol\n",
    "\n",
    "        bg60 = self.bg60Dict[symbol]\n",
    "        bg60.updateBar(bar)\n",
    "\n",
    "        bg30 = self.bg30Dict[symbol]\n",
    "        bg30.updateBar(bar)\n",
    "\n",
    "        bg15 = self.bg15Dict[symbol]\n",
    "        bg15.updateBar(bar)\n",
    "\n",
    "        # 洗价器\n",
    "        if (self.posDict[self.Longpos] > 0):\n",
    "            if (bar.close < self.transactionPrice * (1 - self.stopRatio)) or (\n",
    "                bar.close > self.transactionPrice * (1 + self.profitMultiplier * self.stopRatio)):\n",
    "                self.cancelAll()\n",
    "                self.sell(symbol, bar.close * 0.9, 1)\n",
    "        elif (self.posDict[self.Shortpos] > 0):\n",
    "            if (bar.close > self.transactionPrice * (1 + self.stopRatio)) or (\n",
    "                bar.close < self.transactionPrice * (1 - self.profitMultiplier * self.stopRatio)):\n",
    "                self.cancelAll()\n",
    "                self.cover(symbol, bar.close * 1.1, 1)\n",
    "\n",
    "    # ----------------------------------------------------------------------\n",
    "    # Regression\n",
    "    def on60minBar(self, bar):\n",
    "        symbol = bar.vtSymbol\n",
    "\n",
    "        # 保存K线数据\n",
    "        am60 = self.am60Dict[symbol]\n",
    "        am60.updateBar(bar)\n",
    "\n",
    "        if not am60.inited:\n",
    "            return\n",
    "\n",
    "        trendFastArray = ta.LINEARREG_SLOPE(am60.close, self.trendFastWindow)\n",
    "        trendSlowArray = ta.LINEARREG_SLOPE(am60.close, self.trendSlowWindow)\n",
    "\n",
    "        if trendFastArray[-1] > trendSlowArray[-1] or trendFastArray[-1] > 0:\n",
    "            self.Trend = 1\n",
    "\n",
    "        elif trendFastArray[-1] <= trendSlowArray[-1] or trendSlowArray[-1] < 0:\n",
    "            self.Trend = -1\n",
    "        else:\n",
    "            self.Trend = 0\n",
    "\n",
    "    ## ATR_Slope\n",
    "    def on30minBar(self, bar):\n",
    "        symbol = bar.vtSymbol\n",
    "        # 保存K线数据\n",
    "        am30 = self.am30Dict[symbol]\n",
    "        am30.updateBar(bar)\n",
    "        if not am30.inited:\n",
    "            return\n",
    "\n",
    "        volatilityArray = ta.ATR(am30.high, am30.low, am30.close, self.volatilityWindow)\n",
    "        volatilityThreshold = ta.LINEARREG_SLOPE(volatilityArray, self.volatilityThresholdWindow)\n",
    "        if volatilityThreshold[-1] > 0:\n",
    "            self.Volatility = 1\n",
    "        elif volatilityThreshold[-1] <= 0:\n",
    "            self.Volatility = 0\n",
    "\n",
    "    ## Reverting\n",
    "    def on15minBar(self, bar):\n",
    "        symbol = bar.vtSymbol\n",
    "        am15 = self.am15Dict[symbol]\n",
    "        am15.updateBar(bar)\n",
    "        if not am15.inited:\n",
    "            return\n",
    "\n",
    "        signalMeanArray = ta.MA(am15.close, self.SignalFastWindow)\n",
    "        signalUpperArray = signalMeanArray * (1 + self.revertPercent)\n",
    "        signalLowerArray = signalMeanArray * (1 - self.revertPercent)\n",
    "\n",
    "        if self.posDict[self.Longpos] == 0 and self.posDict[self.Shortpos] == 0:\n",
    "            if self.Trend == 1 and self.Volatility == 1:\n",
    "                if am15.close[-1] >= signalLowerArray[-2] and am15.close[-2] < signalLowerArray[-2]:\n",
    "                    self.buy(symbol, bar.close * 1.1, self.fixedSize)\n",
    "            if self.Trend == -1 and self.Volatility == 1:\n",
    "                if am15.close[-1] <= signalUpperArray[-2] and am15.close[-2] > signalUpperArray[-2]:\n",
    "                    self.short(symbol, bar.close * 0.9, self.fixedSize)\n",
    "\n",
    "                    #         self.saveSyncData()\n",
    "        # 发出状态更新事件\n",
    "        self.putEvent()\n",
    "\n",
    "        # ----------------------------------------------------------------------\n",
    "\n",
    "    def onOrder(self, order):\n",
    "        \"\"\"收到委托变化推送（必须由用户继承实现）\"\"\"\n",
    "        pass\n",
    "\n",
    "    # ----------------------------------------------------------------------\n",
    "    def onTrade(self, trade):\n",
    "        self.transactionPrice = trade.price\n",
    "        self.putEvent()\n",
    "\n",
    "    # ----------------------------------------------------------------------\n",
    "    def onStopOrder(self, so):\n",
    "        \"\"\"停止单推送\"\"\"\n",
    "        pass"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
